using Microsoft.Extensions.DependencyInjection;
using Serilog.Core;
using Serilog.Events;
using SG3L_RAG.Domain.Entities;
using SG3L_RAG.Infrastructure.Persistence;

namespace SG3L_RAG.Infrastructure.Logging
{
    public class DatabaseSink : ILogEventSink
    {
        private readonly IServiceProvider _serviceProvider;

        public DatabaseSink(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }

        public void Emit(LogEvent logEvent)
        {
            // 异步处理，避免阻塞主线程
            Task.Run(async () => await EmitAsync(logEvent));
        }

        private async Task EmitAsync(LogEvent logEvent)
        {
            try
            {
                using var scope = _serviceProvider.CreateScope();
                var dbContext = scope.ServiceProvider.GetRequiredService<SG3LDbContext>();

                var logEntry = Log.Create(
                    type: MapLogLevel(logEvent.Level),
                    content: logEvent.RenderMessage(),
                    exceptionDetail: logEvent.Exception?.ToString()
                );

                await dbContext.Logs.AddAsync(logEntry);
                await dbContext.SaveChangesAsync();
            }
            catch (Exception ex)
            {
                // 避免日志记录失败导致应用程序崩溃
                Console.WriteLine($"Failed to write log to database: {ex.Message}");
            }
        }

        private static string MapLogLevel(LogEventLevel level)
        {
            return level switch
            {
                LogEventLevel.Verbose => "verbose",
                LogEventLevel.Debug => "debug",
                LogEventLevel.Information => "info",
                LogEventLevel.Warning => "warning",
                LogEventLevel.Error => "error",
                LogEventLevel.Fatal => "fatal",
                _ => "unknown"
            };
        }
    }
}
